[Lambda] VPC Lambdaの起動タイムラグを測定してみた
はじめに
2016年2月にVPC内で利用可能となり、RDS、ElastiCache などにプライベートIP接続が可能となった AWS Lambdaですが、 VPC アクセスに用いられるENI(Elastic Network Interface)の作成、アタッチが発生するため、初回実行時に一定の遅延が生じる事が知られています。
この遅延、LambdaのCloudwatchメトリック 所要時間 (Duration)としては計上される事はない為、 イベントをトリガとして起動するLambdaでは、確認する事が困難でした。
今回、簡易な検証ですが、KinesisとLambdaを用いて、VPC Lambdaで生じるタイムラグを確認する機会がありましたので、紹介させて頂きます。
参考リンク
検証方法
概要図
- 現在時刻(ミリ秒)を取得し、Kinesis Streamに取得した時刻情報を投入(Put)する、Lambda(producer)を用意しました
- Kinesisのデータを受信(Get)するLambda(consumer)は、投入時刻と受信時刻の差を求め、CloudWatchLogsに結果を反映します
検証手順
- 1分毎のCloudwatch Eventを3つ用意し、Lambda(producer)は1分に3回起動する設定としました
- 測定は約20時間、Lambda(producer)は1時間に180回、約3500回のLambda関数呼び出し(Invocations)を行いました。
- Lambda(consumer)を、VPC、非VPCに設置し、投入されたデータが受信されるまでの所要時間の違いを比較、VPC Lambdaの遅延を求めました
Lambda ソース
結果
所要時間(タイムラグ)集計
全データ
項目 | VPC | 非VPC |
---|---|---|
平均時間 | 1905.1 | 1896.6 |
標準偏差 | 772.2 | 438.4 |
最大値 | 12971 | 4100 |
最小値 | 1204 | 1260 |
- 測定単位はミリ秒
- 3000件の平均時間、VPCと非VPCの間に大きな差はありませんでした。
- VPC環境では最大約13秒の遅延が5回測定されていました。
VPC,非VPC 所要時間ワースト10
VPC | 非VPC |
---|---|
12971 | 4100 |
12662 | 3740 |
11333 | 3439 |
10811 | 3420 |
10139 | 3380 |
4205 | 3300 |
3859 | 3279 |
3324 | 3260 |
3254 | 3260 |
3234 | 3240 |
ワースト10の値を除外した所要時間集計
項目 | VPC | 非VPC |
---|---|---|
平均時間 | 1850.3 | 1879.3 |
標準偏差 | 355 | 407.9 |
最大値 | 3234 | 3238 |
- ワースト10の値を除外した2990件の結果では、VPC、非VPCのスループットの差はない状態でした。
VPC Lambda 遅延発生時の個別ログ
- 計測期間中、ロググループは5件生成されていました。
- 10秒以上の遅延、今回は全てロググループの先頭行で計測されていました。
- 「10.11.x.x」のIPアドレス(client_hostname_ip)は、Lambda関数内で「hostname -i」で取得しています。
- ロググループの変更があった直前、別ロググループの最終レコードを確認した所、「hostname -i」で取得できるIPアドレスが異なる事が確認され、Lambdaの実行環境の変更があったと予想されます。
まとめ
今回の検証で、VPC Lambda は 初回起動時、及び実行環境の切替時に10秒前後の遅延が確認されました。
発生頻度としては0.数%以下、その存在を許容できるケースも多いと思われますが、 以下のようなAPI Gateway経由での利用など、遅延の影響が大きな箇所で VPC Lambda を利用する場合には、 稀に発生する遅延の存在について留意頂ければと思います。
- ※ 2016年11月現在、API Gatewayの制限としてタイムアウトは30秒となっています
尚、今回の検証により、Lambda実行環境のコンテナ再利用機構により、VPC利用による性能影響は 初回起動の遅延を除けば少ない事が確認できました。
以下のように、Kinesis(Stream)を利用し、ストリームイベント経由で起動したVPC LambdaによるDB更新処理、 数秒のタイムラグを伴う、非同期処理が許容される場合には、DBへの確実な反映や、負荷対策としても 有効性が高い実装と考えられます。
また、DB負荷とのトレードオフになりますが、稀に発生する遅延を極力回避する方策として、 以下のように1回のDB更新、複数の Lambda(consumer) に着火させ、 トランザクションにより先行した更新のみをDBに反映させる事も可能と考えられます。
ただ、確実な同期処理、複数のDB更新をトランザクションで管理し、適切な例外処理も必須などの要求がある場合には、 実行環境としてEC2の利用もご検討ください。